import { everyBodyCanAccess, authenticatedAccess, adminCanAccess } from '../config/auth';
import { DOMAIN_WHITE_LIST } from '../config';
import { pathMatch } from '../utils/common';
import { getPermissionsInRedis } from '../bin/init';
import url from 'url';

/**
 * 权限认证中间件
 * @export
 * @param {*} ctx
 * @param {*} next
 */
export default async function (ctx, next) {
  // 检查域名如果域名在白名单中自动加上跨域请求头
  const origin = ctx.request.headers.origin;
  if (DOMAIN_WHITE_LIST.indexOf(origin) > -1) {
    ctx.set('Access-Control-Allow-Origin', origin);
  }

  // 跳过options请求
  if (ctx.method === 'OPTIONS') {
    await next();
    return;
  }

  // 跳过任何人可以访问的请求
  const currentPath = `${ctx.method} ${url.parse(ctx.url).pathname}`;
  const isEveryBodyCanAccess = everyBodyCanAccess.some(item => {
    return pathMatch(item, currentPath);
  });
  if (isEveryBodyCanAccess) {
    await next();
    return;
  }

  // 如果该请求只允许认证用户访问
  const isAuthenticatedAccess = authenticatedAccess.some(item => {
    return pathMatch(item, currentPath);
  });
  if (isAuthenticatedAccess) {
    if (ctx.state.user) {
      await next();
      return;
    } else {
      ctx.status = 401;
      ctx.body = { ok: false, msg: 'need login', authfail: true };
      console.log(`${ctx.method} ${ctx.url} - 401 No Login`);
      return;
    }
  }

  // 如果是管理员才可以访问的请求
  const isAdminCanAccess = adminCanAccess.some(item => {
    return pathMatch(item, currentPath);
  });
  if (isAdminCanAccess) {
    if (ctx.state.user && ctx.state.user.id) {
      await next();
      return;
    } else {
      ctx.status = 401;
      ctx.body = { ok: false, msg: 'need login', authfail: true };
      console.log(`${ctx.method} ${ctx.url} - 401 No Login`);
      return;
    }
  }

  if (ctx.state.user) {
    // 超级管理员直接放行
    if (ctx.state.user.sign === 'manager') {
      await next();
      return;
    }
    const permissionStr = await getPermissionsInRedis(ctx.state.user.role_id);
    const permissions = permissionStr ? permissionStr.split(',') : [];
    const hasPermission = permissions.some(item => {
      return pathMatch(item, currentPath);
    });

    if (hasPermission) {
      await next();
      return;
    } else {
      ctx.status = 403;
      ctx.body = { ok: false, msg: '暂无权限' };
      console.log(`${ctx.method} ${ctx.url} - 403 Forbidden`);
      return;
    }
  }

  // 以上情况都不是则不放行
  ctx.status = 404;
  ctx.body = { ok: false, msg: '接口未找到' };
  next();
  console.log(`${ctx.method} ${ctx.url} - 404 Interface Not Found`);
}
